package com.usian.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.usian.config.RedisClient;
import com.usian.mapper.*;
import com.usian.pojo.*;
import com.usian.service.ItemService;
import com.usian.utils.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
public class ItemServiceImpl implements ItemService {

    @Autowired
    private TbItemMapper tbItemMapper;
    @Autowired
    private TbItemDescMapper tbItemDescMapper;
    @Autowired
    private TbItemCatMapper tbItemCatMapper;
    @Autowired
    private TbItemParamItemMapper tbItemParamItemMapper;
    @Value("${PROTAL_CATRESULT_KEY}")
    private String PROTAL_CATRESULT_KEY;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Value("${ITEM_INFO}")
    private String ITEM_INFO;
    @Value("${BASE}")
    private String BASE;
    @Value("${DESC}")
    private String DESC;
    @Value("${PARAM}")
    private String PARAM;
    @Value("${ITEM_INFO_EXPIRE}")
    private Integer ITEM_INFO_EXPIRE;
    @Value("${SETNX_BASC_LOCK_KEY}")
    private String SETNX_BASC_LOCK_KEY;
    @Value("${SETNX_DESC_LOCK_KEY}")
    private String SETNX_DESC_LOCK_KEY;
    @Value("${SETNX_PARAM_LOCK_KEY}")
    private String SETNX_PARAM_LOCK_KEY;

    @Override
    public List<TbItem> findAll() {
        return tbItemMapper.selectByExample(new TbItemExample());
    }

    @Override
    public TbItem findById(Long itemId) {
        return tbItemMapper.selectByPrimaryKey(itemId);
    }

    @Override
    public void delete(Long itemId) {
        tbItemMapper.deleteByPrimaryKey(itemId);
    }

    @Override
    public PageResult pageFindAll(Integer page, Integer rows) {
        PageHelper.startPage(page,rows);
        TbItemExample example = new TbItemExample();
        TbItemExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo((byte)1);
        List<TbItem> list = tbItemMapper.selectByExample(example);
        PageInfo<TbItem> pageInfo = new PageInfo<>(list);
        PageResult pageResult = new PageResult();
        pageResult.setPageIndex(pageInfo.getPageNum());
        pageResult.setTotalPage(pageInfo.getPages());
        pageResult.setResult(pageInfo.getList());
        return pageResult;
    }

    @Override
    public Integer deleteItemById(Long itemId) {
        //item_param_item 物理删除
        TbItemParamItemExample tbItemParamItemExample = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = tbItemParamItemExample.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        Integer deleteParamItem = tbItemParamItemMapper.deleteByExample(tbItemParamItemExample);

        //item_desc 物理删除
        Integer deleteDesc = tbItemDescMapper.deleteByPrimaryKey(itemId);

        //item；逻辑删除
        TbItem tbItem = new TbItem();
        tbItem.setStatus((byte)3);
        tbItem.setId(itemId);

        amqpTemplate.convertAndSend("usian_exchage","delete.delete",itemId);
        Integer deleteItem = tbItemMapper.updateByPrimaryKeySelective(tbItem);
        redisClient.del(ITEM_INFO+":"+itemId+":"+BASE);
        redisClient.del(ITEM_INFO+":"+itemId+":"+DESC);
        redisClient.del(ITEM_INFO+":"+itemId+":"+PARAM);
        return deleteParamItem+deleteDesc+deleteItem;
    }

    @Override
    public Integer insertTbItem(TbItem tbItem, String desc, String itemParams) {
        long itemId = IDUtils.genItemId();
        tbItem.setId(itemId);
        Date date = new Date();
        tbItem.setCreated(date);
        tbItem.setUpdated(date);
        tbItem.setStatus((byte)1);
        tbItem.setPrice(tbItem.getPrice()*100);
        Integer addItem = tbItemMapper.insertSelective(tbItem);

        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(itemId);
        tbItemDesc.setItemDesc(desc);
        tbItemDesc.setCreated(date);
        tbItemDesc.setUpdated(date);
        Integer addItemDesc = tbItemDescMapper.insertSelective(tbItemDesc);

        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        tbItemParamItem.setItemId(itemId);
        tbItemParamItem.setCreated(date);
        tbItemParamItem.setUpdated(date);
        tbItemParamItem.setParamData(itemParams);
        Integer addItemParam = tbItemParamItemMapper.insertSelective(tbItemParamItem);
        amqpTemplate.convertAndSend("usian_exchage","item.add",itemId);
        return addItem+addItemDesc+addItemParam;
    }

    @Override
    public Map<String,Object> preUpdateItem(Long itemId) {
        Map<String,Object> map = new HashMap<>();
        //根据商品id查看商品信息
        TbItem tbItem = tbItemMapper.selectByPrimaryKey(itemId);
        map.put("item",tbItem);

        //根据商品id查看商品描述
        TbItemDesc tbItemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);
        if(tbItemDesc!=null){
            map.put("itemDesc",tbItemDesc.getItemDesc());
        }else{
            map.put("itemDesc","");
        }

        //根据商品id查看类别名称
        TbItemCat tbItemCat = tbItemCatMapper.selectByPrimaryKey(tbItem.getCid());
        map.put("itemCat",tbItemCat.getName());

        //根据商品id查看itemParamItem
        TbItemParamItemExample tbItemParamItemExample = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = tbItemParamItemExample.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        List<TbItemParamItem> tbItemParamItems = tbItemParamItemMapper.selectByExampleWithBLOBs(tbItemParamItemExample);
        if (tbItemParamItems.size()>0){
            TbItemParamItem tbItemParamItem = tbItemParamItems.get(0);
            map.put("itemParamItem",tbItemParamItem.getParamData());
        }
        return map;
    }

    @Override
    public Integer updateTbItem(TbItem tbItem, String desc, String itemParams) {
        tbItem.setPrice(tbItem.getPrice()*100);
        tbItem.setUpdated(new Date());
        Integer updateItem = tbItemMapper.updateByPrimaryKeySelective(tbItem);

        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(tbItem.getId());
        tbItemDesc.setItemDesc(desc);
        tbItemDesc.setUpdated(new Date());
        Integer updateItemDesc = tbItemDescMapper.updateByPrimaryKeySelective(tbItemDesc);

        TbItemParamItemExample tbItemParamItemExample = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = tbItemParamItemExample.createCriteria();
        criteria.andItemIdEqualTo(tbItem.getId());
        List<TbItemParamItem> tbItemParamItems = tbItemParamItemMapper.selectByExample(tbItemParamItemExample);
        Integer updateItemParam = 0;
        TbItemParamItem tbItemParamItem = null;
        if (tbItemParamItems.size()>0){
            tbItemParamItem = tbItemParamItems.get(0);
            tbItemParamItem.setParamData(itemParams);
            tbItemParamItem.setUpdated(new Date());
            updateItemParam = tbItemParamItemMapper.updateByPrimaryKeySelective(tbItemParamItem);
        }
        redisClient.set(ITEM_INFO+":"+tbItem.getId()+":"+BASE,tbItem);
        redisClient.set(ITEM_INFO+":"+tbItem.getId()+":"+DESC,tbItemDesc);
        redisClient.set(ITEM_INFO+":"+tbItem.getId()+":"+PARAM,tbItemParamItem);
        amqpTemplate.convertAndSend("usian_exchage","item.update",tbItem.getId());
        return updateItem+updateItemDesc+updateItemParam;
    }

    @Override
    public CatResult selectItemCategoryAll() {
        CatResult catResultRedis = (CatResult) redisClient.get(PROTAL_CATRESULT_KEY);
        if (catResultRedis!=null){
            return catResultRedis;
        }
        CatResult catResult = new CatResult();
        catResult.setData(getCatList(0L));
        redisClient.set(PROTAL_CATRESULT_KEY,catResult);
        return catResult;
    }

    @Override
    public TbItem selectItemInfo(Long itemId) {
        TbItem item = (TbItem) redisClient.get(ITEM_INFO+":"+itemId+":"+BASE);
        if (item!=null){
            return item;
        }
        TbItem tbItem = new TbItem();
        //缓存击穿
        if (redisClient.setnx(SETNX_BASC_LOCK_KEY+":"+itemId,itemId,30L)){
            tbItem = tbItemMapper.selectByPrimaryKey(itemId);
            //缓存穿透
            if(tbItem==null){
                redisClient.set(ITEM_INFO+":"+itemId+":"+BASE,new TbItem(1L,"系统繁忙"));
                redisClient.expire(ITEM_INFO+":"+itemId+":"+BASE,60);
            }else{
                redisClient.set(ITEM_INFO+":"+itemId+":"+BASE,tbItem);
                redisClient.expire(ITEM_INFO+":"+itemId+":"+BASE,ITEM_INFO_EXPIRE);
            }
        }else{
            try {
                Thread.sleep(3000);
                this.selectItemInfo(itemId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return tbItem;
    }

    @Override
    public TbItemDesc selectItemDescByItemId(Long itemId) {
        TbItemDesc itemDesc = (TbItemDesc) redisClient.get(ITEM_INFO+":"+itemId+":"+DESC);
        if (itemDesc!=null){
            return itemDesc;
        }
        TbItemDesc tbItemDesc = new TbItemDesc();
        //缓存击穿
        if (redisClient.setnx(SETNX_DESC_LOCK_KEY+":"+itemId,itemId,30L)){
            tbItemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);
            //缓存穿透
            if(tbItemDesc==null){
                redisClient.set(ITEM_INFO+":"+itemId+":"+DESC,new TbItemDesc(1L,"系统繁忙"));
                redisClient.expire(ITEM_INFO+":"+itemId+":"+DESC,60);
            }else{
                redisClient.set(ITEM_INFO+":"+itemId+":"+DESC,tbItemDesc);
                redisClient.expire(ITEM_INFO+":"+itemId+":"+DESC,ITEM_INFO_EXPIRE);
            }
        }else{
            try {
                Thread.sleep(3000);
                this.selectItemDescByItemId(itemId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return tbItemDesc;
    }

    @Override
    public TbItemParamItem selectTbItemParamItemByItemId(Long itemId) {
        TbItemParamItem itemParamItem = (TbItemParamItem) redisClient.get(ITEM_INFO+":"+itemId+":"+PARAM);
        if (itemParamItem!=null){
            return itemParamItem;
        }
        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        //缓存击穿
        if (redisClient.setnx(SETNX_PARAM_LOCK_KEY+":"+itemId,itemId,30L)){
            TbItemParamItemExample tbItemParamItemExample = new TbItemParamItemExample();
            TbItemParamItemExample.Criteria criteria = tbItemParamItemExample.createCriteria();
            criteria.andItemIdEqualTo(itemId);
            List<TbItemParamItem> tbItemParamItems = tbItemParamItemMapper.selectByExampleWithBLOBs(tbItemParamItemExample);
            tbItemParamItem = tbItemParamItems.get(0);

            //缓存穿透
            if (tbItemParamItem==null){
                redisClient.set(ITEM_INFO+":"+itemId+":"+PARAM,new TbItemParamItem(1L,"系统繁忙"));
                redisClient.expire(ITEM_INFO+":"+itemId+":"+PARAM,60);
            }else{
                redisClient.set(ITEM_INFO+":"+itemId+":"+PARAM,tbItemParamItem);
                redisClient.expire(ITEM_INFO+":"+itemId+":"+PARAM,ITEM_INFO_EXPIRE);
            }
        }else {
            try {
                Thread.sleep(3000);
                this.selectTbItemParamItemByItemId(itemId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return tbItemParamItem;
    }

    public List<?> getCatList(Long parentId){
        TbItemCatExample tbItemCatExample = new TbItemCatExample();
        TbItemCatExample.Criteria criteria = tbItemCatExample.createCriteria();
        criteria.andParentIdEqualTo(parentId);
        //查出来父id为0的所有数据
        List<TbItemCat> catList = tbItemCatMapper.selectByExample(tbItemCatExample);
        List list = new ArrayList();
        int count = 0;
        for (TbItemCat tbItemCat : catList) {
            //判断是不是父节点
            if (tbItemCat.getIsParent()){
                //如果是，把名字和item复制到catnode对象中并继续调用该方法
                CatNode catNode = new CatNode();
                catNode.setName(tbItemCat.getName());
                catNode.setItem(getCatList(tbItemCat.getId()));
                list.add(catNode);
                count++;
                //只展示18条数据
                if (count==18){
                    break;
                }
            }else {
                //如果不是父节点就把名字存到集合中
                list.add(tbItemCat.getName());
            }
        }
        return list;
    }
}
